package com.system.enterprisemanagementsystem.aop;

import com.alibaba.fastjson.JSON;
import com.system.enterprisemanagementsystem.anno.LogOperation;
import com.system.enterprisemanagementsystem.mapper.OperateLogMapper;
import com.system.enterprisemanagementsystem.pojo.OperateLog;
import com.system.enterprisemanagementsystem.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * AOP 操作日志记录切面
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    private OperateLogMapper operateLogMapper;

    /**
     * 环绕通知：拦截带有 @LogOperation 注解的方法
     */
    @Around("@annotation(olog)")
    public Object around(ProceedingJoinPoint joinPoint, LogOperation olog) throws Throwable {
        long start = System.currentTimeMillis(); // 记录方法执行开始时间
        Object result = null;

        try {
            // ✅ 执行原始方法
            result = joinPoint.proceed();
            return result;
        } finally {
            long costTime = System.currentTimeMillis() - start;

            // ✅ 构造日志对象
            OperateLog logRecord = new OperateLog();

            // 操作人ID（从UserContext获取）
            Integer userId = UserContext.getUserId();
            log.info("userID = {}",  userId);
            logRecord.setOperateEmpId(userId);
            logRecord.setOperateTime(LocalDateTime.now());

            // 执行类名与方法名
            logRecord.setClassName(joinPoint.getTarget().getClass().getName());
            logRecord.setMethodName(joinPoint.getSignature().getName());

            // 方法参数
            try {
                String params = JSON.toJSONString(joinPoint.getArgs());
                logRecord.setMethodParams(truncate(params, 1000));
            } catch (Exception e) {
                log.warn("序列化方法参数失败", e);
            }

            // 返回值
            try {
                String returnVal = JSON.toJSONString(result);
                logRecord.setReturnValue(truncate(returnVal, 2000));
            } catch (Exception e) {
                log.warn("序列化返回值失败", e);
            }

            // 执行时长
            logRecord.setCostTime((Long) costTime);

            // ✅ 保存日志
            try {
                operateLogMapper.insert(logRecord);
                log.info("操作日志记录成功 -> {}", logRecord);
            } catch (Exception e) {
                log.error("保存操作日志失败", e);
            }
        }
    }

    /** 工具方法：超长截断字符串 */
    private String truncate(String str, int maxLength) {
        if (str == null) return null;
        return str.length() > maxLength ? str.substring(0, maxLength) : str;
    }
}
